package com.ir.stat.spark.service;

import com.ir.stat.spark.utils.JsonBuilder;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@Component
public class StorageService {

    public static String INDEX_RECORDS_MAPPING = "RecordsMapping";
    public static String INDEX_EXT_RECORDS_MAPPING = "ExtRecordsMapping";
    public static String INDEX_RESOURCES = "Resources";
//    public static String INDEX_DATASOURCES = "Datasources";
//    public static String INDEX_FILES = "Files";

    @Value("${storage.root:/tmp/stat}")
    private String storageRoot;

    @Value("${storage.file.name:db_snapshot}")
    private String storageFileName;

    private Map<String, Map> storage = new HashMap<>();

    @PostConstruct
    public void init() {
        recoverFromDisk();
    }

    public long getLong(String index, String key) {
        Map<String, Object> map = getMap(index);
        if (map != null && map.containsKey(key)) {
            Object val = map.get(key);
            return Long.valueOf(val.toString());
        }
        return 0l;
    }

    public String getString(String index, String key) {
        Map<String, String> map = getMap(index);
        if (map != null) {
            return map.get(key);
        }
        return null;
    }

    public void put(String index, String key, Object value) {
        Map map = getMap(index);
        if (map != null) {
            map.put(key, value);
        }
    }

    public Map getMap(String key) {
        if (storage.containsKey(key)) {
            return storage.get(key);
        } else {
            Map map = new ConcurrentHashMap();
            storage.put(key, map);
            return map;
        }
    }

    public void removeMap(String key) {
        if (storage.containsKey(key)) {
            storage.remove(key);
        }
    }

    public synchronized void recoverFromDisk() {
        File dbFilePath = new File(storageRoot, storageFileName);
        if (dbFilePath.exists()) {
            try {
                BufferedReader br = new BufferedReader(new FileReader(dbFilePath));
                String json = br.readLine();
                if (StringUtils.isNotBlank(json)) {
                    Map map = JsonBuilder.getInstance().fromJson(json, HashMap.class);
                    storage.putAll(map);
                }
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void flushToDisk() {
        File root = new File(storageRoot);
        if (!root.exists()) {
            root.mkdirs();
        }
        File dbFilePath = new File(storageRoot, storageFileName);
        String json = JsonBuilder.getInstance().toJson(storage);
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new FileWriter(dbFilePath));
            bw.write(json);
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
